<template>
  <el-form
    :model="spuInfo"
    label-width="100px"
    :rules="spuRules"
    ref="spuFormRef"
  >
    <el-form-item label="SPU名称" prop="spuName">
      <el-input v-model="spuInfo.spuName" placeholder="SPU名称"></el-input>
    </el-form-item>
    <el-form-item label="品牌" prop="tmId">
      <el-select placeholder="请选择品牌" v-model="spuInfo.tmId">
        <el-option
          v-for="tm in trademarkList"
          :key="tm.id"
          :label="tm.tmName"
          :value="tm.id"
        />
      </el-select>
    </el-form-item>
    <el-form-item label="SPU描述" prop="description">
      <el-input
        v-model="spuInfo.description"
        type="textarea"
        :rows="4"
      ></el-input>
    </el-form-item>
    <el-form-item label="SPU图片" prop="spuImageList">
      <el-upload
        v-model:file-list="spuInfo.spuImageList"
        :action="`${BASE_URL}/admin/product/upload`"
        list-type="picture-card"
        :on-preview="handlePictureCardPreview"
        :on-remove="handleRemove"
        :on-success="handleAvatarSuccess"
        :before-upload="beforeAvatarUpload"
      >
        <el-icon>
          <Plus />
        </el-icon>
      </el-upload>
      <el-dialog v-model="dialogVisible">
        <img w-full :src="dialogImageUrl" alt="Preview Image" />
      </el-dialog>
    </el-form-item>
    <el-form-item label="销售属性" prop="spuSaleAttrList">
      <!-- <el-select
        v-model="spuInfo.spuSaleAttr"
        :placeholder="`还剩下${baseSaleAttrList.length}个未选择`"
      > -->
      <el-select
        v-model="spuInfo.spuSaleAttr"
        :placeholder="`还剩下${filterBaseSaleAttrList.length}个未选择`"
      >
        <el-option
          v-for="baseSaleAttr in filterBaseSaleAttrList"
          :key="baseSaleAttr.id"
          :label="baseSaleAttr.name"
          :value="baseSaleAttr.name"
        />
      </el-select>
      <el-button
        type="primary"
        @click="addSpuSaleAttr"
        :disabled="!spuInfo.spuSaleAttr"
        >添加销售属性</el-button
      >
      <!-- </el-form-item>
    <el-form-item> -->
      <el-table border :data="spuInfo.spuSaleAttrList">
        <el-table-column
          label="序号"
          width="80px"
          type="index"
          align="center"
        ></el-table-column>
        <el-table-column label="属性名" prop="saleAttrName"></el-table-column>
        <el-table-column label="属性值名称列表">
          <template v-slot="{ row, $index }">
            <el-tag
              v-for="tag in row.spuSaleAttrValueList"
              :key="tag"
              class="mx-1"
              closable
              :disable-transitions="false"
              @close="handleClose(row, tag)"
            >
              {{ tag.saleAttrValueName }}
            </el-tag>
            <el-input
              v-if="row.inputVisible"
              ref="InputRef"
              v-model="inputValue"
              class="ml-1 w-20"
              size="small"
              @keyup.enter="handleInputConfirm(row)"
              @blur="handleInputConfirm(row)"
            />
            <el-button
              v-else
              class="button-new-tag ml-1"
              size="small"
              @click="showInput(row)"
            >
              + New
            </el-button>
          </template>
        </el-table-column>
        <el-table-column label="操作">
          <template v-slot="{ row, $index }">
            <el-popconfirm
              confirm-button-text="确定"
              cancel-button-text="取消"
              :icon="InfoFilled"
              icon-color="#626AEF"
              title="真的确定要删除此条数据么?"
              @confirm="deleteAttr($index)"
            >
              <template #reference>
                <el-button
                  title="删除"
                  type="danger"
                  size="small"
                  :icon="Delete"
                />
              </template>
            </el-popconfirm>
          </template>
        </el-table-column>
      </el-table>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="spuSubmitForm(spuFormRef)"
        >保存</el-button
      >
      <el-button @click="emits('changeScene', 1)">取消</el-button>
    </el-form-item>
  </el-form>
</template>

<script lang="ts">
export default {
  name: 'SpuForm',
}
</script>

<script lang="ts" setup>
import { ref, onMounted, reactive, computed, nextTick } from 'vue'
import { Plus, Delete, InfoFilled } from '@element-plus/icons-vue'
import { ElMessage, ElInput } from 'element-plus'
import type {
  UploadProps,
  UploadFile,
  UploadFiles,
  FormInstance,
  FormRules,
} from 'element-plus'
import {
  reqGetAllTrademarkList,
  reqGetBaseSaleAttrList,
  reqGetSpuImageList,
  reqGetSpuSaleAttrList,
  reqSaveSpuInfo,
  reqUpdateSpuInfo,
} from '@/api/product/spu'
import { useCategoryListStore } from '@/stores/categoryList'

const categoryStore = useCategoryListStore()

const props = defineProps(['currentSpuInfo'])
const emits = defineEmits(['changeScene'])
// 添加或是删除基础销售属性值相关的变量
const inputValue = ref('')
const dynamicTags = ref(['Tag 1', 'Tag 2', 'Tag 3'])
const inputVisible = ref(false) //这里就不要用公用的了,会有小问题
const InputRef = ref<InstanceType<typeof ElInput>>()

// 定义两个变量 来存储品牌列表和基础销售属性
const trademarkList = ref([])
const baseSaleAttrList = ref([])

const dialogImageUrl = ref('')
const dialogVisible = ref(false)
// 动态读取环境变量中的值
const BASE_URL = import.meta.env.VITE_API_URL
// const fileList = ref<UploadUserFile[]>([])
const fileList = []

// 定义一个存储spu相关数据的变量
const spuInfo = reactive({
  spuName: '', // spu的名称
  tmId: '', // spu品牌
  description: '', // spu描述
  spuImageList: [], // 存储spu图片的数组
  spuSaleAttrList: [], // 基本销售属性
  spuSaleAttr: '', // 收集选中的属性 颜色 版本  尺寸
  category3Id: '', // 三级id

  ...props.currentSpuInfo,
})

const formSize = ref('default')
const spuFormRef = ref<FormInstance>()
// 添加校验规则
const spuRules = reactive<FormRules>({
  spuName: [
    { required: true, message: '请输入SPU名称', trigger: 'blur' },
    { min: 1, max: 10, message: '长度在1--10之间', trigger: 'blur' },
  ],
  tmId: [{ required: true, message: '请选择品牌名称', trigger: 'change' }],
  description: [{ required: true, message: '请添加SPU描述', trigger: 'blur' }],
  spuImageList: [
    {
      type: 'array',
      required: true,
      message: '请至少上传一张图片',
      trigger: 'change',
    },
  ],
  spuSaleAttrList: [
    {
      type: 'array',
      required: true,
      message: '请添加销售属性',
      trigger: 'change',
    },
  ],
})

// 1. 组件一挂载完毕，就要去发送请求 获取品牌列表和销售属性的值
onMounted(async () => {
  // 我们可以借助于一个Promise.all([])方法，一次性发送多个请求，
  // 当请求成功后，会将数据按书写顺序依次赋值  只要成功就会按书写顺序 无论哪个快慢
  // Promise.all([])如果有一个失败了，则整体都是失败的

  try {
    // 原来的两个函数
    let promises = [reqGetAllTrademarkList(), reqGetBaseSaleAttrList()]
    const id = spuInfo.id

    if (id) {
      //  // 如果id有值，说明此时是编辑操作，需要再加上两个接口函数
      promises = promises.concat([
        reqGetSpuImageList(id),
        //一个根据spuId获取销售属性列表的接口函数
        reqGetSpuSaleAttrList(id),
      ])
    }

    const [
      responseTrademarkList,
      responseBaseSaleAttrList,
      responseSpuImageList,
      responseSpuSaleAttrList,
    ] = await Promise.all(promises)
    // console.log('aw', responseTrademarkList, responseBaseSaleAttrList)
    // responseTrademarkList是所有品牌数据，responseBaseSaleAttrList是那三个销售属性,颜色,版本
    trademarkList.value = responseTrademarkList
    baseSaleAttrList.value = responseBaseSaleAttrList
    // console.log('ss',responseSpuImageList,responseSpuSaleAttrList)
    if (responseSpuImageList && responseSpuSaleAttrList) {
      // spuInfo.spuImageList = responseSpuImageList
      spuInfo.spuImageList = responseSpuImageList.map((item) => {
        return {
          ...item,
          name: item.imgName,
          url: item.imgUrl,
        }
      })
      spuInfo.spuSaleAttrList = responseSpuSaleAttrList
    }
  } catch (error) {
    ElMessage.error('获取品牌或属性失败')
  }
})

// 2. 删除图片时执行的事件处理程序
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
  // console.log('aa', uploadFile, uploadFiles)
  // uploadFile表示删除了的图片的信息
  // uploadFiles 表示剩余的图片信息

  // 将剩余的图片信息存到这个数组当中，在最终上传之前，再处理一下
  spuInfo.spuImageList = uploadFiles
}
// 3. 图片预览时要执行的事件处理程序
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
  dialogImageUrl.value = uploadFile.url!
  dialogVisible.value = true
}
// 4. 图片上传成功后要执行的事件处理程序
const handleAvatarSuccess: UploadProps['onSuccess'] = (
  response: any,
  uploadFile: UploadFile,
  uploadFiles: UploadFiles
) => {
  // response是服务器响应回来的结果  里面的data属性就有图片在服务器端的地址
  // uploadFile 是经过改造的响应对象 不但包含图片在服务器响应回来的结果  还包含图片本身的信息
  console.log('up', response, uploadFile, uploadFiles)
  // uploadFiles 相当于是上传的所有的图片的数组
  // 收集上传成功后的图片信息
  // spuInfo.spuImageList.push({
  //   imgName: uploadFile.name,
  //   imgUrl: response.data
  // })

  // 这个时候uploadFiles中图片的名字是name地址是在response中的data中
  spuInfo.spuImageList = uploadFiles //

  // 清除校验规则
  spuFormRef.value!.clearValidate(['spuImageList'])
}

// 5. 图片上传之前校验时要执行的事件处理程序
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
  const imgTypes = ['image/jpeg', 'image/jpg', 'image/png'] //限制上传图片的格式
  // if (rawFile.type !== 'image/jpeg') {
  if (!imgTypes.includes(rawFile.type)) {
    //进到这里说明格式不符合要求
    ElMessage.error('上传的图片格式必须是JPG/JPEG/PNG格式。。。')
    return false
  } else if (rawFile.size / 1024 / 1024 > 2) {
    // 进到这里说明图片大小大于2m
    ElMessage.error('图片最大不能超过2M...')
    return false
  }
  return true
}

// 6. 添加基础销售属性
const addSpuSaleAttr = () => {
  // 6.1 添加属性之间要做个判断
  // 如果有某个属性没有属性值的话，是不能添加新属性的
  const spuSaleAttrList = spuInfo.spuSaleAttrList //这个就是装着属性的那个列表
  if (
    spuSaleAttrList.length &&
    spuSaleAttrList.some((item) => item.spuSaleAttrValueList.length == 0)
  ) {
    ElMessage.error('属性值不能为空。。。')
    return // 不要向下执行  也就是不要添加新的属性
  }

  const id = baseSaleAttrList.value.find(
    (item) => item.name === spuInfo.spuSaleAttr
  ).id
  // 6.2 添加新的属性
  spuInfo.spuSaleAttrList.push({
    baseSaleAttrId: id,
    // 给当前行对象添加一个属性，用于控制按钮和输入框的显示
    inputVisible: false,
    saleAttrName: spuInfo.spuSaleAttr, // 属性名 颜色 版本  尺寸
    spuSaleAttrValueList: [], // 当前属性名对应的那些详细的属性值
  })

  // 清空一下下拉框
  spuInfo.spuSaleAttr = ''
}

// 7. 使用计算属性 来处理销售属性的显示
const filterBaseSaleAttrList = computed(() => {
  // baseSaleAttrList是用来存储基础销售属性的列表
  // spuInfo.spuSaleAttrList是销售属性相关的数组
  return baseSaleAttrList.value.filter((baseSalue) => {
    return !spuInfo.spuSaleAttrList.find(
      (item) => baseSalue.name === item.saleAttrName
    )
  })
})

// 8. 删除销售属性
const deleteAttr = (index: number) => {
  spuInfo.spuSaleAttrList.splice(index, 1)
}

// 以下三个函数是与销售属性值相关的函数
// const handleClose = (tag: string) => {
const handleClose = (row, tag) => {
  // dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1)
  row.spuSaleAttrValueList.splice(row.spuSaleAttrValueList.indexOf(tag), 1)
}

// 点击添加显示输入框
const showInput = (row) => {
  // inputVisible.value = true
  row.inputVisible = true
  nextTick(() => {
    InputRef.value!.input!.focus()
  })
}

// 失去焦点和按下回车键触发
const handleInputConfirm = (row) => {
  if (inputValue.value) {
    // 这个if判断是为了优化重复属性能够添加的问题
    if (
      row.spuSaleAttrValueList.find(
        (item) => item.saleAttrValueName === inputValue.value
      )
    ) {
      // 如果进到这里就说明输入框里面的和已有的属性值重复了
      ElMessage.error('属性值不能重复...')
      // 然后把输入框给清空并隐藏
      row.inputVisible = false
      inputValue.value = ''
      return // 不再向下执行
    }
    const id = baseSaleAttrList.value.find(
      (item) => item.name === row.saleAttrName
    ).id

    // dynamicTags.value.push(inputValue.value)
    row.spuSaleAttrValueList.push({
      baseSaleAttrId: id,
      saleAttrName: row.saleAttrName, // 当前属性名称 比如 颜色 版本 尺寸
      saleAttrValueName: inputValue.value, // 具体的属性值
    })
  }
  // inputVisible.value = false
  row.inputVisible = false
  inputValue.value = ''
}

// 保存SpuInfo 到服务器
const spuSubmitForm = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  await formEl.validate(async (valid, fields) => {
    if (valid) {
      // 校验通过走这里
      // console.log('submit!')
      // 对于要添加的属性值，再做一个验证，如果属性名有，而属性值为空的话，也不能提交
      // 再判断一下，基础销售是不是有属性值，如果有一项无值 不能提交
      const spuSaleAttrList = spuInfo.spuSaleAttrList
      if (
        spuSaleAttrList.length &&
        !spuSaleAttrList.every((item) => item.spuSaleAttrValueList.length)
      ) {
        ElMessage.error('有属性值为空，请重新添加...')
        return // 不要添加了
      }

      // 提取一下图片的内容
      // spuInfo.spuImageList = spuInfo.spuImageList.map((item) => {
      //   return {
      //     imgName: item.name,
      //     imgUrl: item.response.data,
      //   }
      // })
      // 解决图片加载不出来的问题，（因为穿过去的图片没有名称和链接）
      spuInfo.spuImageList = spuInfo.spuImageList.map((item) => {
        return {
          imgUrl: item.response?.data || item.url,
          imgName: item.name,
        }
      })

      spuInfo.category3Id = categoryStore.category3Id
      if (spuInfo.id) {
        // 此时是更新操作
        await reqUpdateSpuInfo(spuInfo)
      } else {
        // 才是真正的添加spuInfo
        await reqSaveSpuInfo(spuInfo)
      }

      ElMessage.success('spu添加成功...')

      emits('changeScene', 1)
    } else {
      console.log('error submit!', fields)
    }
  })
}
</script>

<style></style>
